home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
ole2book.zip
/
CHAP11.ZIP
/
CHAP11
/
POLYLINE
/
POLYWIN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-22
|
12KB
|
428 lines
/*
* POLYWIN.CPP
*
* Window procedure for the polyline drawing window and support functions.
* This window is not complicated. On creation it allocates a block of
* memory for a POLYLINEDATA structure that contains 20 POINTs. We do not
* attempt to reallocate this array at all just to maintain simplicity.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include <windows.h>
#include <ole2.h>
#include "polyline.h"
/*
* PolylineWndProc
*
* Purpose:
* Window procedure for the polyline drawing window.
*/
LRESULT __export FAR PASCAL PolylineWndProc(HWND hWnd, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
LPCPolyline ppl;
PAINTSTRUCT ps;
HDC hDC;
POINT pt;
RECT rc;
ppl=(LPCPolyline)GetWindowLong(hWnd, PLWL_STRUCTURE);
switch (iMsg)
{
case WM_CREATE:
ppl=(LPCPolyline)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLong(hWnd, PLWL_STRUCTURE, (LONG)ppl);
//CHAPTER11MOD
//Moved call to New() to Init.
ppl->m_hWnd=hWnd;
//End CHAPTER11MOD
break;
case WM_PAINT:
hDC=BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
ppl->Draw(hDC, FALSE, TRUE, &rc, NULL);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
//Stop if we are already at the limit.
if (CPOLYLINEPOINTS==ppl->m_pl.cPoints)
{
MessageBeep(0);
break;
}
//Convert the points into 0-32767 range
GetClientRect(hWnd, &rc);
pt=MAKEPOINT(lParam);
ppl->PointScale(&rc, &pt, FALSE);
ppl->m_pl.rgpt[ppl->m_pl.cPoints++]=pt;
//Draw the lines to this new point only.
hDC=GetDC(hWnd);
ppl->Draw(hDC, FALSE, FALSE, &rc, NULL);
ReleaseDC(hWnd, hDC);
if (NULL!=ppl->m_pAdv)
ppl->m_pAdv->OnPointChange();
//CHAPTER11MOD
//Notifications necessary to support compound documents.
ppl->SendAdvise(OBJECTCODE_DATACHANGED);
//End CHAPTER11MOD
break;
default:
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
return 0L;
}
/*
* CPolyline::Draw
*
* Purpose:
* Paints the current line in the polyline window.
*
* Parameters:
* hDC HDC to draw on, could be a metafile or printer DC.
* fMetafile BOOL indicating if hDC is a metafile or not, so we
* can avoid operations that RIP.
* fEntire BOOL indicating if we should draw the entire figure
* or not.
* pRect LPRECT defining the bounds on hDC in which to draw.
* ppl LPPOLYLINEDATA to draw. If NULL, we use the current.
*
* Return Value:
* None
*/
void CPolyline::Draw(HDC hDC, BOOL fMetafile, BOOL fEntire, LPRECT pRect
, LPPOLYLINEDATA ppl)
{
//CHAPTER11MOD
HBRUSH hBrush;
HPEN hPen;
HGDIOBJ hObj1, hObj2;
UINT i, j;
POINT pt[2];
int nDC;
if (NULL==ppl)
ppl=&m_pl;
nDC=SaveDC(hDC);
//Printer and frozen differences handled in IViewObject::Draw
hPen=CreatePen(ppl->iLineStyle, 1, ppl->rgbLine);
hObj1=SelectObject(hDC, hPen);
hBrush=CreateSolidBrush(ppl->rgbBackground);
hObj2=SelectObject(hDC, hBrush);
SetBkColor(hDC, ppl->rgbBackground);
/*
* Either draw the entire figure or just a single point. The
* entire figure also includes erasing the background completely,
* since hDC may be a metafile DC. Drawing a single point just
* updates the figure for that new point.
*/
if (fEntire || 0==ppl->cPoints)
{
//Erase the background for bitmaps and metafiles.
SelectObject(hDC, GetStockObject(NULL_PEN));
Rectangle(hDC, pRect->left, pRect->top, pRect->right+1, pRect->bottom+1);
SelectObject(hDC, hPen);
/*
* If we are drawing the entire figure, then loop through each
* point drawing a line to each successive point.
*/
for (i=0; i < ppl->cPoints; i++)
{
for (j=i; j < ppl->cPoints; j++)
{
pt[0]=ppl->rgpt[i];
pt[1]=ppl->rgpt[j];
PointScale(pRect, &pt[0], TRUE);
PointScale(pRect, &pt[1], TRUE);
MoveTo(hDC, pt[0].x, pt[0].y);
LineTo(hDC, pt[1].x, pt[1].y);
}
}
}
else
{
/*
* If we are only drawing the last point, just cycle once
* through previous points.
*/
//Get the last point entered in the array.
j=ppl->cPoints-1;
pt[0]=ppl->rgpt[j];
PointScale(pRect, &pt[0], TRUE);
for (i=0; i < j; i++)
{
pt[1]=ppl->rgpt[i];
PointScale(pRect, &pt[1], TRUE);
MoveTo(hDC, pt[0].x, pt[0].y);
LineTo(hDC, pt[1].x, pt[1].y);
}
}
//If we only had one point, draw a dot to indicate it's position.
if (1==ppl->cPoints)
{
pt[0]=ppl->rgpt[0];
PointScale(pRect, &pt[0], TRUE);
SetPixel(hDC, pt[0].x, pt[0].y, ppl->rgbLine);
}
SelectObject(hDC, hObj1);
SelectObject(hDC, hObj2);
DeleteObject(hBrush);
DeleteObject(hPen);
RestoreDC(hDC, nDC);
return;
//End CHAPTER11MOD
}
/*
* CPolyline::PointScale
*
* Purpose:
* Scales a point to or from a relative window coordinate to a 0-32767
* coordinate.
*
* Parameters:
* pRect LPRECT of the window.
* ppt LPPOINT to convert
* fScaleToWindow BOOL indicating direction of scaling.
*
* Return Value:
* None
*/
void CPolyline::PointScale(LPRECT pRect, LPPOINT ppt, BOOL fScaleToWindow)
{
DWORD cx, cy;
//Window size
cx=(DWORD)(pRect->right-pRect->left);
cy=(DWORD)(pRect->bottom-pRect->top);
//Prevent crashes
if (0L==cx) cx=1;
if (0L==cy) cy=1;
//Must use DWORD to insure proper scaling.
//CHAPTER11MOD
/*
* As an in-proc server we may not have a rectangle where the
* top left was (0,0) which was always true when we drew to
* a Polyline window. But this may be a container's hDC in which
* case we'd better place the points in the container's rectangle.
* That is, we have to add/subtract pRect->left and ->top in
* these calculations.
*/
if (fScaleToWindow)
{
ppt->x=pRect->left+(UINT)(((DWORD)ppt->x*cx) >> 15);
ppt->y=pRect->top+(UINT)(((DWORD)ppt->y*cy) >> 15);
}
else
{
ppt->x=(UINT)(((DWORD)(ppt->x - pRect->left) << 15)/cx);
ppt->y=(UINT)(((DWORD)(ppt->y - pRect->top) << 15)/cy);
}
//End CHAPTER11MOD
return;
}
//CHAPTER11MOD
/*
* PolyDlgProc
*
* Purpose:
* Dialog procedure for a window in which to display the Polyline
* for editing. This pretty much handles all editing functionality
* for the embedded object.
*/
BOOL __export FAR PASCAL PolyDlgProc(HWND hDlg, UINT iMsg
, WPARAM wParam, LPARAM lParam)
{
LPCPolyline ppl=NULL;
WORD w1, w2;
HWND hWnd;
RECT rc;
POINT pt;
UINT uID, uTemp;
UINT cx, cy;
w1=(WORD)GetProp(hDlg, PROP_SELECTOR);
w2=(WORD)GetProp(hDlg, PROP_OFFSET);
ppl=(LPCPolyline)MAKELP(w1, w2);
switch (iMsg)
{
case WM_INITDIALOG:
ppl=(LPCPolyline)lParam;
ppl->m_hDlg=hDlg;
SetProp(hDlg, PROP_SELECTOR, (HANDLE)SELECTOROF(ppl));
SetProp(hDlg, PROP_OFFSET, (HANDLE)OFFSETOF(ppl));
//Center the dialog on the screen
cx=GetSystemMetrics(SM_CXSCREEN);
cy=GetSystemMetrics(SM_CYSCREEN);
GetWindowRect(hDlg, &rc);
SetWindowPos(hDlg, NULL, (cx-(rc.right-rc.left))/2
, (cy-(rc.bottom-rc.top))/2, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
//Create the Polyline to exactly cover the static rectangle.
hWnd=GetDlgItem(hDlg, ID_POLYLINERECT);
GetWindowRect(hWnd, &rc);
SETPOINT(pt, rc.left, rc.top);
ScreenToClient(hDlg, &pt);
//Set the polyline just within the black frame
SetRect(&rc, pt.x, pt.y, pt.x+(rc.right-rc.left)
, pt.y+(rc.bottom-rc.top));
InflateRect(&rc, -1, -1);
//Try to create the window.
ppl->m_pIPolyline->Init(hDlg, &rc, WS_CHILD | WS_VISIBLE, ID_POLYLINE);
//Set the initial line style radiobutton.
ppl->m_pIPolyline->LineStyleGet(&uTemp);
CheckRadioButton(hDlg, ID_LINESOLID, ID_LINEDASHDOTDOT
, uTemp+ID_LINEMIN);
ppl->SendAdvise(OBJECTCODE_SHOWOBJECT);
ppl->SendAdvise(OBJECTCODE_SHOWWINDOW);
return TRUE;
case WM_COMMAND:
uID=LOWORD(wParam);
switch (uID)
{
case IDOK:
RemoveProp(hDlg, PROP_SELECTOR);
RemoveProp(hDlg, PROP_OFFSET);
if (NULL!=ppl)
{
ppl->SendAdvise(OBJECTCODE_HIDEWINDOW);
ppl->SendAdvise(OBJECTCODE_CLOSED);
ppl->m_hDlg=NULL;
}
EndDialog(hDlg, TRUE);
break;
case ID_UNDO:
if (NULL!=ppl)
ppl->m_pIPolyline->Undo();
break;
case ID_COLORLINE:
case ID_COLORBACK:
if (NULL!=ppl)
{
UINT i;
COLORREF rgColors[16];
CHOOSECOLOR cc;
//Invoke the color chooser for either color
uTemp=(ID_COLORBACK==uID)
? POLYLINECOLOR_BACKGROUND : POLYLINECOLOR_LINE;
for (i=0; i<16; i++)
rgColors[i]=RGB(0, 0, i*16);
_fmemset(&cc, 0, sizeof(CHOOSECOLOR));
cc.lStructSize=sizeof(CHOOSECOLOR);
cc.lpCustColors=rgColors;
cc.hwndOwner=hDlg;
cc.Flags=CC_RGBINIT;
ppl->m_pIPolyline->ColorGet(uTemp, &cc.rgbResult);
if (ChooseColor(&cc))
{
//rgColor is just some COLORREF pointer
ppl->m_pIPolyline->ColorSet(uTemp, cc.rgbResult
, rgColors);
}
}
break;
case ID_LINESOLID:
case ID_LINEDASH:
case ID_LINEDOT:
case ID_LINEDASHDOT:
case ID_LINEDASHDOTDOT:
if (NULL!=ppl)
ppl->m_pIPolyline->LineStyleSet(uID-ID_LINEMIN, &uTemp);
break;
}
break;
case WM_CLOSE:
//Close just like we hit the "Close" button.
SendCommand(hDlg, IDOK, 0, 0);
break;
}
return FALSE;
}
//End CHAPTER11MOD